<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>井字棋</title>
  <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css"
    integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
  <link rel="stylesheet" href="main.css">
  <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
  <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
  <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
</head>

<body>
  <div id="root"></div>

  <script type="text/babel">
    function Square(props) {
      return (
        <button className="square btn btn-outline-secondary" onClick={props.onClick}>
          {props.value}
        </button>
      );
    }

    function calculateWinner(squares) {
      const lines = [
        [0, 1, 2],[3, 4, 5],[6, 7, 8],[0, 3, 6],
        [1, 4, 7],[2, 5, 8],[0, 4, 8],[2, 4, 6],
      ];
      for (let i = 0; i < lines.length; i++) {
        const [a, b, c] = lines[i];
        if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
          return squares[a];
        }
      }
      return null;
    }

    class Board extends React.Component {
      renderSquare(x, y) {
        return (
          <Square value={this.props.squares[x]} onClick={() => this.props.onClick(x, y)} />
        );
      }

      render() {
        return (
          <div>
            <div className="board-row">
              {this.renderSquare(0)}
              {this.renderSquare(1)}
              {this.renderSquare(2)}
            </div>
            <div className="board-row">
              {this.renderSquare(3)}
              {this.renderSquare(4)}
              {this.renderSquare(5)}
            </div>
            <div className="board-row">
              {this.renderSquare(6)}
              {this.renderSquare(7)}
              {this.renderSquare(8)}
            </div>
          </div>
        );
      }
    }

    class Game extends React.Component {
      constructor(props) {
        super(props);
        this.state = {
          history: [
            {
              squares: Array(9).fill(null),
            },
          ],
          xIsNext: true,
          stepNumber: 0,
        }
      }

      handleClick(x, y) {
        const history = this.state.history.slice(0, this.state.stepNumber + 1);
        const current = history[history.length - 1];
        const squares = current.squares.slice();
        if(calculateWinner(squares) || squares[x]) {
          return;
        }
        squares[x] = this.state.xIsNext ? 'X' : 'O';

        this.setState({
          history: history.concat([{
            squares: squares,
          }]), 
          xIsNext: !this.state.xIsNext,
          stepNumber: history.length,
        });
      }

      jumpTo(step) {
        this.setState({
          stepNumber: step,
          xIsNext: (step % 2) === 0,
        })
      }

      render() {
        const history = this.state.history;
        const current = history[this.state.stepNumber];
        const location = current.location;
        const winner = calculateWinner(current.squares);
        const moves = history.map((item, index) => {
          const desc = index ? 'Go to move #' + index : 'Go to move start';
          return (
            <li key={index}>
              <button className="btn btn-outline-secondary btn-sm" type="button" onClick={() => this.jumpTo(index)}>{desc} (x, y)</button>
            </li>
          );
        });

        let status;
        const fillLength = current.squares.filter((item) => item != null).length;
        if(winner) {
          status = '恭喜 ' + winner + ' 获得了本次的胜利👏🏻👏🏻👏🏻';
        } else if(fillLength === 9) {
          status = '和棋了，再来一局定胜负吧';
        } else {
          status = '该你落子了: ' + (this.state.xIsNext ? 'X' : 'O');
        }

        return (
          <div className="container">
            <h1 className="mt-5 mb-5 text-center">井字棋（Tic Tac Toe）</h1>
            <div className="message mb-5 text-center">{status}</div>
            <div className="row justify-content-center">
              <div className="col-md-auto">
                <Board squares={current.squares} onClick={(x, y) => this.handleClick(x, y)}  />
              </div>
              <div className="col-md-auto">
                <ol className="step-item">{moves}</ol>
              </div>
            </div>
          </div>
        );
      }
    }

    ReactDOM.render(
      <Game />,
      document.getElementById('root')
    );

  </script>
</body>

</html>